﻿using System;
using System.Collections.Generic;
using System.Text;

using Microsoft.Xna.Framework.Input;

namespace Daybreak.Core.Input
{
    /// <summary>
    /// Event driven keyboard device
    /// </summary>
    public sealed class KeyboardDevice
    {
        #region Custom Types

        public enum Language
        {
            Rus,
            Eng
        }

        /// <summary>
        /// <para>Defines the key press modes.</para>
        /// </summary>
        public enum KeyPressMode
        {
            /// <summary>
            /// <para>No key pressed.</para>
            /// </summary>
            None,

            /// <summary>
            /// <para>A key is pressed for the first time.</para>
            /// </summary>
            KeyPressNoRepeat,

            /// <summary>
            /// <para>The key, still pressed, have to be repeated.</para>
            /// </summary>
            KeyPressRepeat
        }

        #endregion

        public static char[] RussianLower;
        public static char[] RussianUpper;
        public static char[] EnglishLower;
        public static char[] EnglishUpper;

        #region Private members

        public TimeSpanWatcher TimeStep;

        private KeyEventArgs _pressedKeyArgs;
        private KeyEventArgs _releasedKeyArgs;

        private Language _lang;

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private KeyboardState _lastState;

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private bool _isShiftPressed;
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private bool _isAltPressed;
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private bool _isTabPressed;
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private bool _isControlPressed;
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private double _lapsOfTimeBetweenTwoManaging;

        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private int _caracterRepeatRate;
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private int _caracterRepeatDelay;
        [System.Diagnostics.DebuggerBrowsable(System.Diagnostics.DebuggerBrowsableState.Never)]
        private KeyPressMode _mode;
        private DateTime _firstKeyDownRepeatTime;
        #endregion

        static KeyboardDevice()
        {
            RussianLower = new char[255];
            EnglishLower = new char[255];

            RussianUpper = new char[255];
            EnglishUpper = new char[255];

            #region russian lower mapping
            RussianLower[(int)Keys.Back] = (char)0;
            RussianLower[(int)Keys.Tab] = ' ';
            RussianLower[(int)Keys.Enter] = '\n';
            RussianLower[(int)Keys.Pause] = (char)0;
            RussianLower[(int)Keys.CapsLock] = (char)0;
            RussianLower[(int)Keys.Escape] = (char)0;
            RussianLower[(int)Keys.Space] = ' ';
            RussianLower[(int)Keys.PageUp] = (char)0;
            RussianLower[(int)Keys.PageDown] = (char)0;
            RussianLower[(int)Keys.End] = (char)0;
            RussianLower[(int)Keys.Home] = (char)0;
            RussianLower[(int)Keys.Left] = (char)0;
            RussianLower[(int)Keys.Up] = (char)0;
            RussianLower[(int)Keys.Right] = (char)0;
            RussianLower[(int)Keys.Down] = (char)0;
            RussianLower[(int)Keys.Select] = (char)0;
            RussianLower[(int)Keys.Print] = (char)0;
            RussianLower[(int)Keys.Execute] = (char)0;
            RussianLower[(int)Keys.PrintScreen] = (char)0;
            RussianLower[(int)Keys.Insert] = (char)0;
            RussianLower[(int)Keys.Delete] = (char)0;
            RussianLower[(int)Keys.Help] = (char)0;
            //     Used for miscellaneous characters; it can vary by keyboard.
            RussianLower[(int)Keys.D0] = '0';
            RussianLower[(int)Keys.D1] = '1';
            RussianLower[(int)Keys.D2] = '2';
            RussianLower[(int)Keys.D3] = '3';
            RussianLower[(int)Keys.D4] = '4';
            RussianLower[(int)Keys.D5] = '5';
            RussianLower[(int)Keys.D6] = '6';
            RussianLower[(int)Keys.D7] = '7';
            RussianLower[(int)Keys.D8] = '8';
            RussianLower[(int)Keys.D9] = '9';

            RussianLower[(int)Keys.A] = 'ф';
            RussianLower[(int)Keys.B] = 'и';
            RussianLower[(int)Keys.C] = 'с';
            RussianLower[(int)Keys.D] = 'в';
            RussianLower[(int)Keys.E] = 'у';
            RussianLower[(int)Keys.F] = 'а';
            RussianLower[(int)Keys.G] = 'п';
            RussianLower[(int)Keys.H] = 'р';
            RussianLower[(int)Keys.I] = 'ш';
            RussianLower[(int)Keys.J] = 'о';
            RussianLower[(int)Keys.K] = 'л';
            RussianLower[(int)Keys.L] = 'д';
            RussianLower[(int)Keys.M] = 'ь';
            RussianLower[(int)Keys.N] = 'т';
            RussianLower[(int)Keys.O] = 'щ';
            RussianLower[(int)Keys.P] = 'з';
            RussianLower[(int)Keys.Q] = 'й';
            RussianLower[(int)Keys.R] = 'к';
            RussianLower[(int)Keys.S] = 'ы';
            RussianLower[(int)Keys.T] = 'е';
            RussianLower[(int)Keys.U] = 'г';
            RussianLower[(int)Keys.V] = 'м';
            RussianLower[(int)Keys.W] = 'ц';
            RussianLower[(int)Keys.X] = 'ч';
            RussianLower[(int)Keys.Y] = 'н';
            RussianLower[(int)Keys.Z] = 'я';

            RussianLower[(int)Keys.LeftWindows] = (char)0;
            RussianLower[(int)Keys.RightWindows] = (char)0;
            RussianLower[(int)Keys.Apps] = (char)0;
            RussianLower[(int)Keys.Sleep] = (char)0;

            RussianLower[(int)Keys.NumPad0] = '0';
            RussianLower[(int)Keys.NumPad1] = '1';
            RussianLower[(int)Keys.NumPad2] = '2';
            RussianLower[(int)Keys.NumPad3] = '3';
            RussianLower[(int)Keys.NumPad4] = '4';
            RussianLower[(int)Keys.NumPad5] = '5';
            RussianLower[(int)Keys.NumPad6] = '6';
            RussianLower[(int)Keys.NumPad7] = '7';
            RussianLower[(int)Keys.NumPad8] = '8';
            RussianLower[(int)Keys.NumPad9] = '9';

            RussianLower[(int)Keys.Multiply] = '*';
            RussianLower[(int)Keys.Add] = '+';
            RussianLower[(int)Keys.Separator] = (char)0;
            RussianLower[(int)Keys.Subtract] = '-';
            RussianLower[(int)Keys.Decimal] = (char)0;
            RussianLower[(int)Keys.Divide] = '/';

            RussianLower[(int)Keys.F1] = (char)0;
            RussianLower[(int)Keys.F2] = (char)0;
            RussianLower[(int)Keys.F3] = (char)0;
            RussianLower[(int)Keys.F4] = (char)0;
            RussianLower[(int)Keys.F5] = (char)0;
            RussianLower[(int)Keys.F6] = (char)0;
            RussianLower[(int)Keys.F7] = (char)0;
            RussianLower[(int)Keys.F8] = (char)0;
            RussianLower[(int)Keys.F9] = (char)0;
            RussianLower[(int)Keys.F10] = (char)0;
            RussianLower[(int)Keys.F11] = (char)0;
            RussianLower[(int)Keys.F12] = (char)0;
            RussianLower[(int)Keys.F13] = (char)0;
            RussianLower[(int)Keys.F14] = (char)0;
            RussianLower[(int)Keys.F15] = (char)0;
            RussianLower[(int)Keys.F16] = (char)0;
            RussianLower[(int)Keys.F17] = (char)0;
            RussianLower[(int)Keys.F18] = (char)0;
            RussianLower[(int)Keys.F19] = (char)0;
            RussianLower[(int)Keys.F20] = (char)0;
            RussianLower[(int)Keys.F21] = (char)0;
            RussianLower[(int)Keys.F22] = (char)0;
            RussianLower[(int)Keys.F23] = (char)0;
            RussianLower[(int)Keys.F24] = (char)0;

            RussianLower[(int)Keys.NumLock] = (char)0;
            RussianLower[(int)Keys.Scroll] = (char)0;
            RussianLower[(int)Keys.LeftShift] = (char)0;
            RussianLower[(int)Keys.RightShift] = (char)0;
            RussianLower[(int)Keys.LeftControl] = (char)0;
            RussianLower[(int)Keys.RightControl] = (char)0;
            RussianLower[(int)Keys.LeftAlt] = (char)0;
            RussianLower[(int)Keys.RightAlt] = (char)0;
            RussianLower[(int)Keys.BrowserBack] = (char)0;
            RussianLower[(int)Keys.BrowserForward] = (char)0;
            RussianLower[(int)Keys.BrowserRefresh] = (char)0;
            RussianLower[(int)Keys.BrowserStop] = (char)0;
            RussianLower[(int)Keys.BrowserSearch] = (char)0;
            RussianLower[(int)Keys.BrowserFavorites] = (char)0;
            RussianLower[(int)Keys.BrowserHome] = (char)0;
            RussianLower[(int)Keys.VolumeMute] = (char)0;
            RussianLower[(int)Keys.VolumeDown] = (char)0;
            RussianLower[(int)Keys.VolumeUp] = (char)0;
            RussianLower[(int)Keys.MediaNextTrack] = (char)0;
            RussianLower[(int)Keys.MediaPreviousTrack] = (char)0;
            RussianLower[(int)Keys.MediaStop] = (char)0;
            RussianLower[(int)Keys.MediaPlayPause] = (char)0;
            RussianLower[(int)Keys.LaunchMail] = (char)0;
            RussianLower[(int)Keys.SelectMedia] = (char)0;
            RussianLower[(int)Keys.LaunchApplication1] = (char)0;
            RussianLower[(int)Keys.LaunchApplication2] = (char)0;

            RussianLower[(int)Keys.OemSemicolon] = 'ж';
            RussianLower[(int)Keys.OemPlus] = '=';
            RussianLower[(int)Keys.OemComma] = 'б';
            RussianLower[(int)Keys.OemMinus] = '-';
            RussianLower[(int)Keys.OemPeriod] = 'ю';
            RussianLower[(int)Keys.OemQuestion] = '.';
            RussianLower[(int)Keys.OemTilde] = 'ё';
            RussianLower[(int)Keys.ChatPadGreen] = (char)0;
            RussianLower[(int)Keys.ChatPadOrange] = (char)0;
            RussianLower[(int)Keys.OemOpenBrackets] = 'х';
            RussianLower[(int)Keys.OemPipe] = '\\';
            RussianLower[(int)Keys.OemCloseBrackets] = 'ъ';
            RussianLower[(int)Keys.OemQuotes] = 'э';
            RussianLower[(int)Keys.Oem8] = (char)0;
            RussianLower[(int)Keys.OemBackslash] = (char)0;
            RussianLower[(int)Keys.ProcessKey] = (char)0;
            RussianLower[(int)Keys.Attn] = (char)0;
            RussianLower[(int)Keys.Crsel] = (char)0;
            RussianLower[(int)Keys.Exsel] = (char)0;
            RussianLower[(int)Keys.EraseEof] = (char)0;
            RussianLower[(int)Keys.Play] = (char)0;
            RussianLower[(int)Keys.Zoom] = (char)0;
            RussianLower[(int)Keys.Pa1] = (char)0;
            RussianLower[(int)Keys.OemClear] = (char)0;
            #endregion

            #region russian upper mapping
            RussianUpper[(int)Keys.Back] = (char)0;
            RussianUpper[(int)Keys.Tab] = ' ';
            RussianUpper[(int)Keys.Enter] = '\n';
            RussianUpper[(int)Keys.Pause] = (char)0;
            RussianUpper[(int)Keys.CapsLock] = (char)0;
            RussianUpper[(int)Keys.Escape] = (char)0;
            RussianUpper[(int)Keys.Space] = ' ';
            RussianUpper[(int)Keys.PageUp] = (char)0;
            RussianUpper[(int)Keys.PageDown] = (char)0;
            RussianUpper[(int)Keys.End] = (char)0;
            RussianUpper[(int)Keys.Home] = (char)0;
            RussianUpper[(int)Keys.Left] = (char)0;
            RussianUpper[(int)Keys.Up] = (char)0;
            RussianUpper[(int)Keys.Right] = (char)0;
            RussianUpper[(int)Keys.Down] = (char)0;
            RussianUpper[(int)Keys.Select] = (char)0;
            RussianUpper[(int)Keys.Print] = (char)0;
            RussianUpper[(int)Keys.Execute] = (char)0;
            RussianUpper[(int)Keys.PrintScreen] = (char)0;
            RussianUpper[(int)Keys.Insert] = (char)0;
            RussianUpper[(int)Keys.Delete] = (char)0;
            RussianUpper[(int)Keys.Help] = (char)0;
            //     Used for miscellaneous characters; it can vary by keyboard.
            RussianUpper[(int)Keys.D0] = ')';
            RussianUpper[(int)Keys.D1] = '!';
            RussianUpper[(int)Keys.D2] = '"';
            RussianUpper[(int)Keys.D3] = '#';
            RussianUpper[(int)Keys.D4] = ';';
            RussianUpper[(int)Keys.D5] = '%';
            RussianUpper[(int)Keys.D6] = ':';
            RussianUpper[(int)Keys.D7] = '?';
            RussianUpper[(int)Keys.D8] = '*';
            RussianUpper[(int)Keys.D9] = '(';

            RussianUpper[(int)Keys.A] = 'Ф';
            RussianUpper[(int)Keys.B] = 'И';
            RussianUpper[(int)Keys.C] = 'С';
            RussianUpper[(int)Keys.D] = 'В';
            RussianUpper[(int)Keys.E] = 'У';
            RussianUpper[(int)Keys.F] = 'А';
            RussianUpper[(int)Keys.G] = 'П';
            RussianUpper[(int)Keys.H] = 'Р';
            RussianUpper[(int)Keys.I] = 'Ш';
            RussianUpper[(int)Keys.J] = 'О';
            RussianUpper[(int)Keys.K] = 'Л';
            RussianUpper[(int)Keys.L] = 'Д';
            RussianUpper[(int)Keys.M] = 'Ь';
            RussianUpper[(int)Keys.N] = 'Т';
            RussianUpper[(int)Keys.O] = 'Щ';
            RussianUpper[(int)Keys.P] = 'З';
            RussianUpper[(int)Keys.Q] = 'Й';
            RussianUpper[(int)Keys.R] = 'К';
            RussianUpper[(int)Keys.S] = 'Ы';
            RussianUpper[(int)Keys.T] = 'Е';
            RussianUpper[(int)Keys.U] = 'Г';
            RussianUpper[(int)Keys.V] = 'М';
            RussianUpper[(int)Keys.W] = 'Ц';
            RussianUpper[(int)Keys.X] = 'Ч';
            RussianUpper[(int)Keys.Y] = 'Н';
            RussianUpper[(int)Keys.Z] = 'Я';

            RussianUpper[(int)Keys.LeftWindows] = (char)0;
            RussianUpper[(int)Keys.RightWindows] = (char)0;
            RussianUpper[(int)Keys.Apps] = (char)0;
            RussianUpper[(int)Keys.Sleep] = (char)0;

            RussianUpper[(int)Keys.NumPad0] = '0';
            RussianUpper[(int)Keys.NumPad1] = '1';
            RussianUpper[(int)Keys.NumPad2] = '2';
            RussianUpper[(int)Keys.NumPad3] = '3';
            RussianUpper[(int)Keys.NumPad4] = '4';
            RussianUpper[(int)Keys.NumPad5] = '5';
            RussianUpper[(int)Keys.NumPad6] = '6';
            RussianUpper[(int)Keys.NumPad7] = '7';
            RussianUpper[(int)Keys.NumPad8] = '8';
            RussianUpper[(int)Keys.NumPad9] = '9';

            RussianUpper[(int)Keys.Multiply] = '*';
            RussianUpper[(int)Keys.Add] = '+';
            RussianUpper[(int)Keys.Separator] = (char)0;
            RussianUpper[(int)Keys.Subtract] = '-';
            RussianUpper[(int)Keys.Decimal] = (char)0;
            RussianUpper[(int)Keys.Divide] = '/';

            RussianUpper[(int)Keys.F1] = (char)0;
            RussianUpper[(int)Keys.F2] = (char)0;
            RussianUpper[(int)Keys.F3] = (char)0;
            RussianUpper[(int)Keys.F4] = (char)0;
            RussianUpper[(int)Keys.F5] = (char)0;
            RussianUpper[(int)Keys.F6] = (char)0;
            RussianUpper[(int)Keys.F7] = (char)0;
            RussianUpper[(int)Keys.F8] = (char)0;
            RussianUpper[(int)Keys.F9] = (char)0;
            RussianUpper[(int)Keys.F10] = (char)0;
            RussianUpper[(int)Keys.F11] = (char)0;
            RussianUpper[(int)Keys.F12] = (char)0;
            RussianUpper[(int)Keys.F13] = (char)0;
            RussianUpper[(int)Keys.F14] = (char)0;
            RussianUpper[(int)Keys.F15] = (char)0;
            RussianUpper[(int)Keys.F16] = (char)0;
            RussianUpper[(int)Keys.F17] = (char)0;
            RussianUpper[(int)Keys.F18] = (char)0;
            RussianUpper[(int)Keys.F19] = (char)0;
            RussianUpper[(int)Keys.F20] = (char)0;
            RussianUpper[(int)Keys.F21] = (char)0;
            RussianUpper[(int)Keys.F22] = (char)0;
            RussianUpper[(int)Keys.F23] = (char)0;
            RussianUpper[(int)Keys.F24] = (char)0;

            RussianUpper[(int)Keys.NumLock] = (char)0;
            RussianUpper[(int)Keys.Scroll] = (char)0;
            RussianUpper[(int)Keys.LeftShift] = (char)0;
            RussianUpper[(int)Keys.RightShift] = (char)0;
            RussianUpper[(int)Keys.LeftControl] = (char)0;
            RussianUpper[(int)Keys.RightControl] = (char)0;
            RussianUpper[(int)Keys.LeftAlt] = (char)0;
            RussianUpper[(int)Keys.RightAlt] = (char)0;
            RussianUpper[(int)Keys.BrowserBack] = (char)0;
            RussianUpper[(int)Keys.BrowserForward] = (char)0;
            RussianUpper[(int)Keys.BrowserRefresh] = (char)0;
            RussianUpper[(int)Keys.BrowserStop] = (char)0;
            RussianUpper[(int)Keys.BrowserSearch] = (char)0;
            RussianUpper[(int)Keys.BrowserFavorites] = (char)0;
            RussianUpper[(int)Keys.BrowserHome] = (char)0;
            RussianUpper[(int)Keys.VolumeMute] = (char)0;
            RussianUpper[(int)Keys.VolumeDown] = (char)0;
            RussianUpper[(int)Keys.VolumeUp] = (char)0;
            RussianUpper[(int)Keys.MediaNextTrack] = (char)0;
            RussianUpper[(int)Keys.MediaPreviousTrack] = (char)0;
            RussianUpper[(int)Keys.MediaStop] = (char)0;
            RussianUpper[(int)Keys.MediaPlayPause] = (char)0;
            RussianUpper[(int)Keys.LaunchMail] = (char)0;
            RussianUpper[(int)Keys.SelectMedia] = (char)0;
            RussianUpper[(int)Keys.LaunchApplication1] = (char)0;
            RussianUpper[(int)Keys.LaunchApplication2] = (char)0;

            RussianUpper[(int)Keys.OemSemicolon] = 'Ж';
            RussianUpper[(int)Keys.OemPlus] = '+';
            RussianUpper[(int)Keys.OemComma] = 'Б';
            RussianUpper[(int)Keys.OemMinus] = '_';
            RussianUpper[(int)Keys.OemPeriod] = 'Ю';
            RussianUpper[(int)Keys.OemQuestion] = ',';
            RussianUpper[(int)Keys.OemTilde] = 'Ё';
            RussianUpper[(int)Keys.ChatPadGreen] = (char)0;
            RussianUpper[(int)Keys.ChatPadOrange] = (char)0;
            RussianUpper[(int)Keys.OemOpenBrackets] = 'Х';
            RussianUpper[(int)Keys.OemPipe] = '\\';
            RussianUpper[(int)Keys.OemCloseBrackets] = 'Ъ';
            RussianUpper[(int)Keys.OemQuotes] = 'Э';
            RussianUpper[(int)Keys.Oem8] = (char)0;
            RussianUpper[(int)Keys.OemBackslash] = (char)0;
            RussianUpper[(int)Keys.ProcessKey] = (char)0;
            RussianUpper[(int)Keys.Attn] = (char)0;
            RussianUpper[(int)Keys.Crsel] = (char)0;
            RussianUpper[(int)Keys.Exsel] = (char)0;
            RussianUpper[(int)Keys.EraseEof] = (char)0;
            RussianUpper[(int)Keys.Play] = (char)0;
            RussianUpper[(int)Keys.Zoom] = (char)0;
            RussianUpper[(int)Keys.Pa1] = (char)0;
            RussianUpper[(int)Keys.OemClear] = (char)0;
            #endregion

            #region english lower mapping
            EnglishLower[(int)Keys.Back] = (char)0;
            EnglishLower[(int)Keys.Tab] = ' ';
            EnglishLower[(int)Keys.Enter] = '\n';
            EnglishLower[(int)Keys.Pause] = (char)0;
            EnglishLower[(int)Keys.CapsLock] = (char)0;
            EnglishLower[(int)Keys.Escape] = (char)0;
            EnglishLower[(int)Keys.Space] = ' ';
            EnglishLower[(int)Keys.PageUp] = (char)0;
            EnglishLower[(int)Keys.PageDown] = (char)0;
            EnglishLower[(int)Keys.End] = (char)0;
            EnglishLower[(int)Keys.Home] = (char)0;
            EnglishLower[(int)Keys.Left] = (char)0;
            EnglishLower[(int)Keys.Up] = (char)0;
            EnglishLower[(int)Keys.Right] = (char)0;
            EnglishLower[(int)Keys.Down] = (char)0;
            EnglishLower[(int)Keys.Select] = (char)0;
            EnglishLower[(int)Keys.Print] = (char)0;
            EnglishLower[(int)Keys.Execute] = (char)0;
            EnglishLower[(int)Keys.PrintScreen] = (char)0;
            EnglishLower[(int)Keys.Insert] = (char)0;
            EnglishLower[(int)Keys.Delete] = (char)0;
            EnglishLower[(int)Keys.Help] = (char)0;
            //     Used for miscellaneous characters; it can vary by keyboard.
            EnglishLower[(int)Keys.D0] = '0';
            EnglishLower[(int)Keys.D1] = '1';
            EnglishLower[(int)Keys.D2] = '2';
            EnglishLower[(int)Keys.D3] = '3';
            EnglishLower[(int)Keys.D4] = '4';
            EnglishLower[(int)Keys.D5] = '5';
            EnglishLower[(int)Keys.D6] = '6';
            EnglishLower[(int)Keys.D7] = '7';
            EnglishLower[(int)Keys.D8] = '8';
            EnglishLower[(int)Keys.D9] = '9';

            EnglishLower[(int)Keys.A] = 'a';
            EnglishLower[(int)Keys.B] = 'b';
            EnglishLower[(int)Keys.C] = 'c';
            EnglishLower[(int)Keys.D] = 'd';
            EnglishLower[(int)Keys.E] = 'e';
            EnglishLower[(int)Keys.F] = 'f';
            EnglishLower[(int)Keys.G] = 'g';
            EnglishLower[(int)Keys.H] = 'h';
            EnglishLower[(int)Keys.I] = 'i';
            EnglishLower[(int)Keys.J] = 'j';
            EnglishLower[(int)Keys.K] = 'k';
            EnglishLower[(int)Keys.L] = 'l';
            EnglishLower[(int)Keys.M] = 'm';
            EnglishLower[(int)Keys.N] = 'n';
            EnglishLower[(int)Keys.O] = 'o';
            EnglishLower[(int)Keys.P] = 'p';
            EnglishLower[(int)Keys.Q] = 'q';
            EnglishLower[(int)Keys.R] = 'r';
            EnglishLower[(int)Keys.S] = 's';
            EnglishLower[(int)Keys.T] = 't';
            EnglishLower[(int)Keys.U] = 'u';
            EnglishLower[(int)Keys.V] = 'v';
            EnglishLower[(int)Keys.W] = 'w';
            EnglishLower[(int)Keys.X] = 'x';
            EnglishLower[(int)Keys.Y] = 'y';
            EnglishLower[(int)Keys.Z] = 'z';

            EnglishLower[(int)Keys.LeftWindows] = (char)0;
            EnglishLower[(int)Keys.RightWindows] = (char)0;
            EnglishLower[(int)Keys.Apps] = (char)0;
            EnglishLower[(int)Keys.Sleep] = (char)0;

            EnglishLower[(int)Keys.NumPad0] = '0';
            EnglishLower[(int)Keys.NumPad1] = '1';
            EnglishLower[(int)Keys.NumPad2] = '2';
            EnglishLower[(int)Keys.NumPad3] = '3';
            EnglishLower[(int)Keys.NumPad4] = '4';
            EnglishLower[(int)Keys.NumPad5] = '5';
            EnglishLower[(int)Keys.NumPad6] = '6';
            EnglishLower[(int)Keys.NumPad7] = '7';
            EnglishLower[(int)Keys.NumPad8] = '8';
            EnglishLower[(int)Keys.NumPad9] = '9';

            EnglishLower[(int)Keys.Multiply] = '*';
            EnglishLower[(int)Keys.Add] = '+';
            EnglishLower[(int)Keys.Separator] = '/';
            EnglishLower[(int)Keys.Subtract] = '-';
            EnglishLower[(int)Keys.Decimal] = (char)0;
            EnglishLower[(int)Keys.Divide] = '/';

            EnglishLower[(int)Keys.F1] = (char)0;
            EnglishLower[(int)Keys.F2] = (char)0;
            EnglishLower[(int)Keys.F3] = (char)0;
            EnglishLower[(int)Keys.F4] = (char)0;
            EnglishLower[(int)Keys.F5] = (char)0;
            EnglishLower[(int)Keys.F6] = (char)0;
            EnglishLower[(int)Keys.F7] = (char)0;
            EnglishLower[(int)Keys.F8] = (char)0;
            EnglishLower[(int)Keys.F9] = (char)0;
            EnglishLower[(int)Keys.F10] = (char)0;
            EnglishLower[(int)Keys.F11] = (char)0;
            EnglishLower[(int)Keys.F12] = (char)0;
            EnglishLower[(int)Keys.F13] = (char)0;
            EnglishLower[(int)Keys.F14] = (char)0;
            EnglishLower[(int)Keys.F15] = (char)0;
            EnglishLower[(int)Keys.F16] = (char)0;
            EnglishLower[(int)Keys.F17] = (char)0;
            EnglishLower[(int)Keys.F18] = (char)0;
            EnglishLower[(int)Keys.F19] = (char)0;
            EnglishLower[(int)Keys.F20] = (char)0;
            EnglishLower[(int)Keys.F21] = (char)0;
            EnglishLower[(int)Keys.F22] = (char)0;
            EnglishLower[(int)Keys.F23] = (char)0;
            EnglishLower[(int)Keys.F24] = (char)0;

            EnglishLower[(int)Keys.NumLock] = (char)0;
            EnglishLower[(int)Keys.Scroll] = (char)0;
            EnglishLower[(int)Keys.LeftShift] = (char)0;
            EnglishLower[(int)Keys.RightShift] = (char)0;
            EnglishLower[(int)Keys.LeftControl] = (char)0;
            EnglishLower[(int)Keys.RightControl] = (char)0;
            EnglishLower[(int)Keys.LeftAlt] = (char)0;
            EnglishLower[(int)Keys.RightAlt] = (char)0;
            EnglishLower[(int)Keys.BrowserBack] = (char)0;
            EnglishLower[(int)Keys.BrowserForward] = (char)0;
            EnglishLower[(int)Keys.BrowserRefresh] = (char)0;
            EnglishLower[(int)Keys.BrowserStop] = (char)0;
            EnglishLower[(int)Keys.BrowserSearch] = (char)0;
            EnglishLower[(int)Keys.BrowserFavorites] = (char)0;
            EnglishLower[(int)Keys.BrowserHome] = (char)0;
            EnglishLower[(int)Keys.VolumeMute] = (char)0;
            EnglishLower[(int)Keys.VolumeDown] = (char)0;
            EnglishLower[(int)Keys.VolumeUp] = (char)0;
            EnglishLower[(int)Keys.MediaNextTrack] = (char)0;
            EnglishLower[(int)Keys.MediaPreviousTrack] = (char)0;
            EnglishLower[(int)Keys.MediaStop] = (char)0;
            EnglishLower[(int)Keys.MediaPlayPause] = (char)0;
            EnglishLower[(int)Keys.LaunchMail] = (char)0;
            EnglishLower[(int)Keys.SelectMedia] = (char)0;
            EnglishLower[(int)Keys.LaunchApplication1] = (char)0;
            EnglishLower[(int)Keys.LaunchApplication2] = (char)0;

            EnglishLower[(int)Keys.OemSemicolon] = ';';
            EnglishLower[(int)Keys.OemPlus] = '=';
            EnglishLower[(int)Keys.OemComma] = ',';
            EnglishLower[(int)Keys.OemMinus] = '-';
            EnglishLower[(int)Keys.OemPeriod] = '.';
            EnglishLower[(int)Keys.OemQuestion] = '/';
            EnglishLower[(int)Keys.OemTilde] = '`';
            EnglishLower[(int)Keys.ChatPadGreen] = (char)0;
            EnglishLower[(int)Keys.ChatPadOrange] = (char)0;
            EnglishLower[(int)Keys.OemOpenBrackets] = '[';
            EnglishLower[(int)Keys.OemPipe] = '\\';
            EnglishLower[(int)Keys.OemCloseBrackets] = ']';
            EnglishLower[(int)Keys.OemQuotes] = '\'';
            EnglishLower[(int)Keys.Oem8] = (char)0;
            EnglishLower[(int)Keys.OemBackslash] = '\\';
            EnglishLower[(int)Keys.ProcessKey] = (char)0;
            EnglishLower[(int)Keys.Attn] = (char)0;
            EnglishLower[(int)Keys.Crsel] = (char)0;
            EnglishLower[(int)Keys.Exsel] = (char)0;
            EnglishLower[(int)Keys.EraseEof] = (char)0;
            EnglishLower[(int)Keys.Play] = (char)0;
            EnglishLower[(int)Keys.Zoom] = (char)0;
            EnglishLower[(int)Keys.Pa1] = (char)0;
            EnglishLower[(int)Keys.OemClear] = (char)0;
            #endregion

            #region english upper mapping
            EnglishUpper[(int)Keys.Back] = (char)0;
            EnglishUpper[(int)Keys.Tab] = ' ';
            EnglishUpper[(int)Keys.Enter] = '\n';
            EnglishUpper[(int)Keys.Pause] = (char)0;
            EnglishUpper[(int)Keys.CapsLock] = (char)0;
            EnglishUpper[(int)Keys.Escape] = (char)0;
            EnglishUpper[(int)Keys.Space] = ' ';
            EnglishUpper[(int)Keys.PageUp] = (char)0;
            EnglishUpper[(int)Keys.PageDown] = (char)0;
            EnglishUpper[(int)Keys.End] = (char)0;
            EnglishUpper[(int)Keys.Home] = (char)0;
            EnglishUpper[(int)Keys.Left] = (char)0;
            EnglishUpper[(int)Keys.Up] = (char)0;
            EnglishUpper[(int)Keys.Right] = (char)0;
            EnglishUpper[(int)Keys.Down] = (char)0;
            EnglishUpper[(int)Keys.Select] = (char)0;
            EnglishUpper[(int)Keys.Print] = (char)0;
            EnglishUpper[(int)Keys.Execute] = (char)0;
            EnglishUpper[(int)Keys.PrintScreen] = (char)0;
            EnglishUpper[(int)Keys.Insert] = (char)0;
            EnglishUpper[(int)Keys.Delete] = (char)0;
            EnglishUpper[(int)Keys.Help] = (char)0;
            //     Used for miscellaneous characters; it can vary by keyboard.
            EnglishUpper[(int)Keys.D0] = ')';
            EnglishUpper[(int)Keys.D1] = '!';
            EnglishUpper[(int)Keys.D2] = '@';
            EnglishUpper[(int)Keys.D3] = '#';
            EnglishUpper[(int)Keys.D4] = '$';
            EnglishUpper[(int)Keys.D5] = '%';
            EnglishUpper[(int)Keys.D6] = '^';
            EnglishUpper[(int)Keys.D7] = '&';
            EnglishUpper[(int)Keys.D8] = '*';
            EnglishUpper[(int)Keys.D9] = '(';

            EnglishUpper[(int)Keys.A] = 'A';
            EnglishUpper[(int)Keys.B] = 'B';
            EnglishUpper[(int)Keys.C] = 'C';
            EnglishUpper[(int)Keys.D] = 'D';
            EnglishUpper[(int)Keys.E] = 'E';
            EnglishUpper[(int)Keys.F] = 'F';
            EnglishUpper[(int)Keys.G] = 'G';
            EnglishUpper[(int)Keys.H] = 'H';
            EnglishUpper[(int)Keys.I] = 'I';
            EnglishUpper[(int)Keys.J] = 'J';
            EnglishUpper[(int)Keys.K] = 'K';
            EnglishUpper[(int)Keys.L] = 'L';
            EnglishUpper[(int)Keys.M] = 'M';
            EnglishUpper[(int)Keys.N] = 'N';
            EnglishUpper[(int)Keys.O] = 'O';
            EnglishUpper[(int)Keys.P] = 'P';
            EnglishUpper[(int)Keys.Q] = 'Q';
            EnglishUpper[(int)Keys.R] = 'R';
            EnglishUpper[(int)Keys.S] = 'S';
            EnglishUpper[(int)Keys.T] = 'T';
            EnglishUpper[(int)Keys.U] = 'U';
            EnglishUpper[(int)Keys.V] = 'V';
            EnglishUpper[(int)Keys.W] = 'W';
            EnglishUpper[(int)Keys.X] = 'X';
            EnglishUpper[(int)Keys.Y] = 'Y';
            EnglishUpper[(int)Keys.Z] = 'Z';

            EnglishUpper[(int)Keys.LeftWindows] = (char)0;
            EnglishUpper[(int)Keys.RightWindows] = (char)0;
            EnglishUpper[(int)Keys.Apps] = (char)0;
            EnglishUpper[(int)Keys.Sleep] = (char)0;

            EnglishUpper[(int)Keys.NumPad0] = '0';
            EnglishUpper[(int)Keys.NumPad1] = '1';
            EnglishUpper[(int)Keys.NumPad2] = '2';
            EnglishUpper[(int)Keys.NumPad3] = '3';
            EnglishUpper[(int)Keys.NumPad4] = '4';
            EnglishUpper[(int)Keys.NumPad5] = '5';
            EnglishUpper[(int)Keys.NumPad6] = '6';
            EnglishUpper[(int)Keys.NumPad7] = '7';
            EnglishUpper[(int)Keys.NumPad8] = '8';
            EnglishUpper[(int)Keys.NumPad9] = '9';

            EnglishUpper[(int)Keys.Multiply] = '*';
            EnglishUpper[(int)Keys.Add] = '+';
            EnglishUpper[(int)Keys.Separator] = '/';
            EnglishUpper[(int)Keys.Subtract] = '-';
            EnglishUpper[(int)Keys.Decimal] = (char)0;
            EnglishUpper[(int)Keys.Divide] = '/';

            EnglishUpper[(int)Keys.F1] = (char)0;
            EnglishUpper[(int)Keys.F2] = (char)0;
            EnglishUpper[(int)Keys.F3] = (char)0;
            EnglishUpper[(int)Keys.F4] = (char)0;
            EnglishUpper[(int)Keys.F5] = (char)0;
            EnglishUpper[(int)Keys.F6] = (char)0;
            EnglishUpper[(int)Keys.F7] = (char)0;
            EnglishUpper[(int)Keys.F8] = (char)0;
            EnglishUpper[(int)Keys.F9] = (char)0;
            EnglishUpper[(int)Keys.F10] = (char)0;
            EnglishUpper[(int)Keys.F11] = (char)0;
            EnglishUpper[(int)Keys.F12] = (char)0;
            EnglishUpper[(int)Keys.F13] = (char)0;
            EnglishUpper[(int)Keys.F14] = (char)0;
            EnglishUpper[(int)Keys.F15] = (char)0;
            EnglishUpper[(int)Keys.F16] = (char)0;
            EnglishUpper[(int)Keys.F17] = (char)0;
            EnglishUpper[(int)Keys.F18] = (char)0;
            EnglishUpper[(int)Keys.F19] = (char)0;
            EnglishUpper[(int)Keys.F20] = (char)0;
            EnglishUpper[(int)Keys.F21] = (char)0;
            EnglishUpper[(int)Keys.F22] = (char)0;
            EnglishUpper[(int)Keys.F23] = (char)0;
            EnglishUpper[(int)Keys.F24] = (char)0;

            EnglishUpper[(int)Keys.NumLock] = (char)0;
            EnglishUpper[(int)Keys.Scroll] = (char)0;
            EnglishUpper[(int)Keys.LeftShift] = (char)0;
            EnglishUpper[(int)Keys.RightShift] = (char)0;
            EnglishUpper[(int)Keys.LeftControl] = (char)0;
            EnglishUpper[(int)Keys.RightControl] = (char)0;
            EnglishUpper[(int)Keys.LeftAlt] = (char)0;
            EnglishUpper[(int)Keys.RightAlt] = (char)0;
            EnglishUpper[(int)Keys.BrowserBack] = (char)0;
            EnglishUpper[(int)Keys.BrowserForward] = (char)0;
            EnglishUpper[(int)Keys.BrowserRefresh] = (char)0;
            EnglishUpper[(int)Keys.BrowserStop] = (char)0;
            EnglishUpper[(int)Keys.BrowserSearch] = (char)0;
            EnglishUpper[(int)Keys.BrowserFavorites] = (char)0;
            EnglishUpper[(int)Keys.BrowserHome] = (char)0;
            EnglishUpper[(int)Keys.VolumeMute] = (char)0;
            EnglishUpper[(int)Keys.VolumeDown] = (char)0;
            EnglishUpper[(int)Keys.VolumeUp] = (char)0;
            EnglishUpper[(int)Keys.MediaNextTrack] = (char)0;
            EnglishUpper[(int)Keys.MediaPreviousTrack] = (char)0;
            EnglishUpper[(int)Keys.MediaStop] = (char)0;
            EnglishUpper[(int)Keys.MediaPlayPause] = (char)0;
            EnglishUpper[(int)Keys.LaunchMail] = (char)0;
            EnglishUpper[(int)Keys.SelectMedia] = (char)0;
            EnglishUpper[(int)Keys.LaunchApplication1] = (char)0;
            EnglishUpper[(int)Keys.LaunchApplication2] = (char)0;

            EnglishUpper[(int)Keys.OemSemicolon] = ':';
            EnglishUpper[(int)Keys.OemPlus] = '+';
            EnglishUpper[(int)Keys.OemComma] = '<';
            EnglishUpper[(int)Keys.OemMinus] = '_';
            EnglishUpper[(int)Keys.OemPeriod] = '>';
            EnglishUpper[(int)Keys.OemQuestion] = '?';
            EnglishUpper[(int)Keys.OemTilde] = '~';
            EnglishUpper[(int)Keys.ChatPadGreen] = (char)0;
            EnglishUpper[(int)Keys.ChatPadOrange] = (char)0;
            EnglishUpper[(int)Keys.OemOpenBrackets] = '{';
            EnglishUpper[(int)Keys.OemPipe] = '|';
            EnglishUpper[(int)Keys.OemCloseBrackets] = '}';
            EnglishUpper[(int)Keys.OemQuotes] = '"';
            EnglishUpper[(int)Keys.Oem8] = (char)0;
            EnglishUpper[(int)Keys.OemBackslash] = '\\';
            EnglishUpper[(int)Keys.ProcessKey] = (char)0;
            EnglishUpper[(int)Keys.Attn] = (char)0;
            EnglishUpper[(int)Keys.Crsel] = (char)0;
            EnglishUpper[(int)Keys.Exsel] = (char)0;
            EnglishUpper[(int)Keys.EraseEof] = (char)0;
            EnglishUpper[(int)Keys.Play] = (char)0;
            EnglishUpper[(int)Keys.Zoom] = (char)0;
            EnglishUpper[(int)Keys.Pa1] = (char)0;
            EnglishUpper[(int)Keys.OemClear] = (char)0;
            #endregion

        }

        #region Constructors

        /// <summary>
        /// <para>Default constructor.</para>
        /// </summary>
        public KeyboardDevice(float updatePerSecond)
        {
            TimeStep = new TimeSpanWatcher(updatePerSecond);

            this._caracterRepeatRate = 5;
            this._caracterRepeatDelay = 400;

            _pressedKeyArgs = new KeyEventArgs(new Keys[8], 0);
            _releasedKeyArgs = new KeyEventArgs(new Keys[8], 0);

            UpdateKeyboardLanguage();
        }

        #endregion

        /// <summary>
        /// Updates the current keyboard state and triggers events if necessary.
        /// </summary>
        /// <param name="elapsedTime"></param>
        public void Update(float elapsedTime)
        {
            float delta = TimeStep.GetNextDelta(elapsedTime);

            if (delta == 0)
                return;

            UpdateKeyboardLanguage();

            KeyboardState currentKeyboardState = Keyboard.GetState();

            ResetTouch();

            Keys[] keys = currentKeyboardState.GetPressedKeys();

            if (KeyboardDevice.ContainsAltKey(keys))
                this._isAltPressed = true;

            if (KeyboardDevice.ContainsTabKey(keys))
                this._isTabPressed = true;

            if (KeyboardDevice.ContainsShiftKey(keys))
                this._isShiftPressed = true;

            if (KeyboardDevice.ContainsControlKey(keys))
                this._isControlPressed = true;

            _releasedKeyArgs.Reset();

            for (int i = 0; i < _pressedKeyArgs.KeysCount; i++)
            {
                Keys lkey = _pressedKeyArgs.KeyData[i];

                currentKeyboardState.IsKeyUp(lkey);

                _releasedKeyArgs.Add(lkey);

            }

            if (KeysUp != null && _releasedKeyArgs.KeysCount > 0)
                KeysUp(this, _releasedKeyArgs);

            _pressedKeyArgs.Reset();

            DateTime nowTime = DateTime.Now;

            //new pressed keys
            {

                for (int i = 0; i < keys.Length; i++)
                {
                    Keys lkey = keys[i];

                    if (_lastState.IsKeyUp(lkey))
                    {
                        _pressedKeyArgs.Add(lkey);
                        _mode = KeyPressMode.None;
                    }
                    else
                        if ((lkey == Keys.LeftShift) || (lkey == Keys.LeftControl) || (lkey == Keys.LeftAlt) || (lkey == Keys.RightShift) || (lkey == Keys.RightAlt) || (lkey == Keys.RightControl))
                            _pressedKeyArgs.Add(lkey);

                }


                if ((_pressedKeyArgs.KeysCount > 0) && (_mode == KeyPressMode.None))
                {
                    _firstKeyDownRepeatTime = nowTime;
                    _mode = KeyPressMode.KeyPressNoRepeat;

                    if (KeysDown != null)
                        KeysDown(this, _pressedKeyArgs);

                    if (KeysPressed != null)
                        KeysPressed(this, _pressedKeyArgs);
                }
            

            }

            if (this._mode == KeyPressMode.KeyPressNoRepeat)
            {
                if (((TimeSpan)(nowTime - _firstKeyDownRepeatTime)).TotalMilliseconds > CaracterRepeatDelay)
                {
                    _mode = KeyPressMode.KeyPressRepeat;
                }
            }
            else
                if (_mode == KeyPressMode.KeyPressRepeat)
                {
                    if (((TimeSpan)(nowTime - _firstKeyDownRepeatTime)).TotalMilliseconds > CaracterRepeatRate)
                    {
                        _firstKeyDownRepeatTime = nowTime;

                        if (KeysPressed != null)
                            KeysPressed(this, _pressedKeyArgs);
                    }

                }

            _lastState = currentKeyboardState;
        }

        public char KeyToChar(Keys key, bool upper)
        {
            char[] table = null;

            if (upper && _lang == Language.Eng)
                table = EnglishUpper;

            if (!upper && _lang == Language.Eng)
                table = EnglishLower;

            if (upper && _lang == Language.Rus)
                table = RussianUpper;

            if (!upper && _lang == Language.Rus)
                table = RussianLower;

            return table[(int)key];
        }

        private void UpdateKeyboardLanguage()
        {
            _lang = Language.Eng;
        }


        #region Private methods

        private void ResetTouch()
        {

            this._isAltPressed = false;
            this._isControlPressed = false;
            this._isShiftPressed = false;
            this._isTabPressed = false;
        }

        #endregion

        #region Static Utility Methods

        /// <summary>
        /// <para>Indicated if the caracters array specified contains a Tab touch.</para>
        /// </summary>
        /// <param name="keys">Array of Caracters</param>
        /// <returns>Returns true is the array contains a Tab touch.</returns>
        public static bool ContainsTabKey(Keys[] keys)
        {

            for (int i = 0; i < keys.Length;i++ )
            {
                if (keys[i] == Keys.Tab)
                    return true;
            }

            return false;
        }

        /// <summary>
        /// <para>Indicated if the caracters array specified contains a Control touch.</para>
        /// </summary>
        /// <param name="keys">Array of Caracters</param>
        /// <returns>Returns true is the array contains a Control touch.</returns>
        public static bool ContainsControlKey(Keys[] keys)
        {

            for (int i = 0; i < keys.Length; i++)
            {
                if ((keys[i] == Keys.LeftControl) || (keys[i] == Keys.RightControl))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// <para>Indicated if the caracters array specified contains an Alt touch.</para>
        /// </summary>
        /// <param name="keys">Array of Caracters</param>
        /// <returns>Returns true is the array contains an Alt touch.</returns>
        public static bool ContainsAltKey(Keys[] keys)
        {

            for (int i = 0; i < keys.Length; i++)
            {
                if ((keys[i] == Keys.LeftAlt) || (keys[i] == Keys.RightAlt))
                    return true;
            }
            return false;
        }

        /// <summary>
        /// <para>Indicated if the caracters array specified contains a Shift touch.</para>
        /// </summary>
        /// <param name="keys">Array of Caracters</param>
        /// <returns>Returns true is the array contains a Shift touch.</returns>
        public static bool ContainsShiftKey(Keys[] keys)
        {

            for (int i = 0; i < keys.Length; i++)
            {
                if ((keys[i] == Keys.LeftShift) || (keys[i] == Keys.RightShift))
                    return true;
            }
            return false;
        }

        #endregion

        #region Properties

        public Language KeyboardLanguage
        {
            get
            {
                return _lang;
            }
        }

        /// <summary>
        /// <para>Occurs when a key is pressed.</para>
        /// </summary>
        public event KeyEventHandler KeysDown;

        /// <summary>
        /// <para>Occurs when a key is released.</para>
        /// </summary>
        public event KeyEventHandler KeysUp;

        /// <summary>
        /// <para>Occurs repeatly when some keys still pressed</para>
        /// </summary>
        public event KeyEventHandler KeysPressed;

        /// <summary>
        /// <para>Gets the current key press mode..</para>
        /// </summary>
        public KeyPressMode Mode
        {
            get
            {
                return this._mode;
            }
        }

        /// <summary>
        /// <para>Gets the caracter repeat rate.</para>
        /// </summary>
        /// <remarks>Laps of time between the adding of two caracters.</remarks>
        public int CaracterRepeatRate
        {
            get
            {
                return this._caracterRepeatRate;
            }
            set
            {
                this._caracterRepeatRate = value;
            }
        }

        /// <summary>
        /// <para>Gets the caracter repeat delay.</para>
        /// </summary>
        /// <remarks>Laps of time before the adding of caracters when a key stay pressed.</remarks>
        public int CaracterRepeatDelay
        {
            get
            {
                return this._caracterRepeatDelay;
            }
            set
            {
                this._caracterRepeatDelay = value;
            }
        }

        /// <summary>
        /// <para>Gets a sets the laps of time that have to be elapsed between two keyboard managing.</para>
        /// </summary>
        public double LapsOfTimeBetweenTwoManaging
        {
            get
            {
                return this._lapsOfTimeBetweenTwoManaging;
            }
            set
            {
                this._lapsOfTimeBetweenTwoManaging = value;
            }
        }

        /// <summary>
        /// <para>Gets a value indicating if the Tab touch is pressed.</para>
        /// </summary>
        public bool IsTabPressed
        {
            get
            {
                return this._isTabPressed;
            }
        }

        /// <summary>
        /// <para>Gets a value indicating if the Control touch is pressed.</para>
        /// </summary>
        public bool IsControlPressed
        {
            get
            {
                return this._isControlPressed;
            }
        }

        /// <summary>
        /// <para>Gets a value indicating if the Alt touch is pressed.</para>
        /// </summary>
        public bool IsAltPressed
        {
            get
            {
                return this._isAltPressed;
            }
        }

        /// <summary>
        /// <para>Gets a value indicating if the Shift touch is pressed.</para>
        /// </summary>
        public bool IsShiftPressed
        {
            get
            {
                return this._isShiftPressed;
            }
        }

        /// <summary>
        /// <para>Gets the last managed key board state.</para>
        /// </summary>
        public KeyboardState LastState
        {
            get
            {
                return this._lastState;
            }
        }


        #endregion


    }

    /// <summary>
    /// <para>Represents the method that will handle the <see cref="Control.KeyUp"/> or <see cref="Control.KeyDown"/> event of a <see cref="Control"/>.</para>
    /// </summary>
    public delegate void KeyEventHandler(KeyboardDevice sender, KeyEventArgs e);

    /// <summary>
    /// <para>Provides data for the <see cref="Control.KeyDown"/> or <see cref="Control.KeyUp"/> event.</para>
    /// </summary>
    public sealed class KeyEventArgs : EventArgs
    {

        #region Fields

        private bool _handled;
        private readonly Keys[] _keyData;
        private int _keysCount;
        private bool _suppressKeyPress;

        #endregion

        #region Constructors

        /// <summary>
        /// <para>Initializes a new instance of the <see cref="KeyEventArgs"/> class.</para>
        /// </summary>
        /// <param name="keyData">A <see cref="Keys"/> representing the key that was pressed, combined with any modifier flags that indicate which CTRL, SHIFT, and ALT keys were pressed at the same time. Possible values are obtained be applying the bitwise OR (|) operator to constants from the <see cref="Keys"/> enumeration.</param>
        public KeyEventArgs(Keys[] keyData, int count)
        {
            this._keyData = keyData;
            this._keysCount = count;
        }

        public void Reset()
        {
            _handled = false;
            _keysCount = 0;
            _suppressKeyPress = false;
        }

        internal void Add(Keys key)
        {
            if (_keysCount >= _keyData.Length)
                return;

            _keyData[_keysCount++] = key;
        }

        #endregion

        public bool ContainsKey(Keys key)
        {
            for (int i = 0; i < _keysCount; i++)
                if (this._keyData[i] == key)
                    return true;

            return false;

        }

        #region Properties

        /// <summary>
        /// <para>Gets a value indicating whether the ALT key was pressed.</para>
        /// <remarks>Alt Gr key is considered as an ALT key.</remarks>
        /// </summary>
        public bool Alt
        {
            get
            {
                bool result = ContainsKey(Keys.LeftAlt) || ContainsKey(Keys.RightAlt);

                return result;
            }
        }

        /// <summary>
        /// <para>Gets a value indicating whether the Delete key was pressed.</para>
        /// </summary>
        public bool Delete
        {
            get
            {
                return ContainsKey(Keys.Delete);
            }
        }

        /// <summary>
        /// <para>Gets a value indicating whether the Back key was pressed.</para>
        /// </summary>
        public bool Back
        {
            get
            {
                return ContainsKey(Keys.Back);
            }
        }

        /// <summary>
        /// <para>Gets a value indicating whether the CTRL key was pressed.</para>
        /// </summary>
        public bool Control
        {
            get
            {
                bool result = ContainsKey(Keys.LeftControl) || ContainsKey(Keys.RightControl);

                return result;
            }
        }

        /// <summary>
        /// <para>Gets or sets a value indicating whether the event was handled.</para>
        /// </summary>
        public bool Handled
        {
            get
            {
                return this._handled;
            }
            set
            {
                this._handled = value;
            }
        }

        /// <summary>
        /// <para>Gets the key data for a <see cref="KeyDown"/> or <see cref="KeyUp"/> event.</para>
        /// </summary>
        public Keys[] KeyData
        {
            get
            {
                return this._keyData;
            }
        }

        /// <summary>
        /// <para>Gets a value indicating whether the SHIFT key was pressed.</para>
        /// </summary>
        public bool Shift
        {
            get
            {
                bool result = ContainsKey(Keys.LeftShift) || ContainsKey(Keys.RightShift);

                return result;
            }
        }

        /// <summary>
        /// <para>Gets or sets a value indicating whether the key event should be passed on to the underlying control.</para>
        /// </summary>
        public bool SuppressKeyPress
        {
            get
            {
                return this._suppressKeyPress;
            }
            set
            {
                this._suppressKeyPress = value;
                this._handled = value;
            }
        }

        /// <summary>
        /// Gets pressed or released keys count
        /// </summary>
        public int KeysCount
        {
            get { return _keysCount; }
        }

        #endregion

    }

}
